home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / enhkbd.zip / ENHKBD.ASM < prev    next >
Assembly Source File  |  1993-01-04  |  16KB  |  413 lines

  1. ;Assembly language file for ENHKBD unit
  2. ;Written by Kim Kokkonen, TurboPower Software
  3.  
  4. ;Version 1.0, 1/3/88
  5. ;  initial release
  6.  
  7. ;Version 1.1, 1/29/88
  8. ;  support the NumLock key!
  9.  
  10. ;Version 1.2, 2/23/88, with help from Brian Foley
  11. ;  don't let NumLock key affect dedicated cursor pad on enhanced keyboard
  12. ;  minimize conflict with QuickKeys and other int 9 handlers
  13. ;  allow Ctrl-Alt-Del with int 9 installed
  14. ;  add method to disable handlers temporarily
  15. ;  use safer test for enhanced keyboard
  16. ;  support alt-keypad keys with Alt-LeftShift combination
  17. ;  add RestoreKbdVectors routine for use by TSR's
  18.  
  19. ;Released to the public domain
  20.  
  21. DATA    SEGMENT BYTE PUBLIC
  22.         EXTRN   HasEnhancedKbd : BYTE
  23.         EXTRN   EnableEnhanced : BYTE
  24. DATA    ENDS
  25.  
  26. CODE    SEGMENT BYTE PUBLIC
  27.  
  28.         ASSUME  CS:CODE, DS:DATA
  29.  
  30.         PUBLIC  GetIntVec, SetIntVec
  31.         PUBLIC  InitVectors
  32.         PUBLIC  EnhancedKbd
  33.         PUBLIC  NewInt09, NewInt16
  34.  
  35. ;CS-relative variables, easily accessible to interrupt handlers
  36. PrevInt09       LABEL DWORD
  37. PrevInt09Ofs    DW ?
  38. PrevInt09Seg    DW ?
  39. PrevInt16       LABEL DWORD
  40. PrevInt16Ofs    DW ?
  41. PrevInt16Seg    DW ?
  42.  
  43. ;*********************************************************** GetIntVec
  44. ;Return an interrupt vector
  45. ;procedure GetIntVec(IntNo : Byte; var Vector : pointer);
  46.  
  47. GetIntVec PROC NEAR
  48.         PUSH    BP
  49.         MOV     BP,SP
  50.         MOV     AL,[BP+8]               ;Get interrupt number
  51.         MOV     AH,35h
  52.         INT     21h
  53.         MOV     AX,ES                   ;Save interrupt segment
  54.         LES     DI,[BP+4]               ;ES:DI => result
  55.         MOV     ES:[DI],BX              ;Offset
  56.         MOV     ES:[DI+2],AX            ;Segment
  57.         MOV     SP,BP
  58.         POP     BP
  59.         RET     6
  60. GetIntVec ENDP
  61.  
  62. ;*********************************************************** SetIntVec
  63. ;Set an interrupt vector
  64. ;procedure SetIntVec(IntNo : Byte; Vector : Pointer);
  65.  
  66. SetIntVec PROC NEAR
  67.         MOV     BX,SP                   ;Set up stack frame
  68.         PUSH    DS
  69.         LDS     DX,SS:[BX+2]            ;Get interrupt address
  70.         MOV     AL,SS:[BX+6]            ;Get interrupt number
  71.         MOV     AH,25h
  72.         INT     21h
  73.         POP     DS
  74.         RET     6
  75. SetIntVec ENDP
  76.  
  77. ;*********************************************************** EnhancedKbd
  78. ;See if enhanced keyboard BIOS installed
  79. ;function EnhancedKbd : Boolean;
  80.  
  81. EnhancedKbd PROC NEAR
  82.         MOV     AH,05                   ;Stuff buffer function
  83.         MOV     CX,0FFFFh               ;Stuff FFFF
  84.         INT     16h
  85.         MOV     AH,11h                  ;Read enhanced function
  86.         INT     16h
  87.         CMP     AX,0FFFFh               ;Did we read the FFFF?
  88.         MOV     AX,0                    ;Prepare for False
  89.         JNZ     EnhDone
  90.         MOV     AH,10h                  ;Get the key out of the buffer
  91.         INT     16h
  92.         MOV     AX,1                    ;Set to true
  93. EnhDone:
  94.         RET
  95. EnhancedKbd ENDP
  96.  
  97. ;*********************************************************** NewInt09
  98. ;Handle hardware keyboard interrupts
  99.  
  100. IndexTable        LABEL BYTE            ;Table of indexes into WordTable
  101.         DB       0FFh   ;00h
  102.         DB        00    ;01h - Esc
  103.         DB       0FFh   ;02h
  104.         DB       0FFh   ;03h
  105.         DB       0FFh   ;04h
  106.         DB       0FFh   ;05h
  107.         DB       0FFh   ;06h
  108.         DB       0FFh   ;07h
  109.         DB       0FFh   ;08h
  110.         DB       0FFh   ;09h
  111.         DB       0FFh   ;0Ah
  112.         DB       0FFh   ;0Bh
  113.         DB       0FFh   ;0Ch
  114.         DB       0FFh   ;0Dh
  115.         DB        01    ;0Eh - Backspace
  116.         DB        02    ;0Fh - Tab
  117.         DB       0FFh   ;10h
  118.         DB       0FFh   ;11h
  119.         DB       0FFh   ;12h
  120.         DB       0FFh   ;13h
  121.         DB       0FFh   ;14h
  122.         DB       0FFh   ;15h
  123.         DB       0FFh   ;16h
  124.         DB       0FFh   ;17h
  125.         DB       0FFh   ;18h
  126.         DB       0FFh   ;19h
  127.         DB        03    ;1Ah - Left Brack
  128.         DB        04    ;1Bh - Right Brack
  129.         DB        05    ;1Ch - Enter
  130.         DB       0FFh   ;1Dh
  131.         DB       0FFh   ;1Eh
  132.         DB       0FFh   ;1Fh
  133.         DB       0FFh   ;20h
  134.         DB       0FFh   ;21h
  135.         DB       0FFh   ;22h
  136.         DB       0FFh   ;23h
  137.         DB       0FFh   ;24h
  138.         DB       0FFh   ;25h
  139.         DB       0FFh   ;26h
  140.         DB        06    ;27h - Semicolon
  141.         DB        07    ;28h - Quote
  142.         DB        08    ;29h - Backquote
  143.         DB       0FFh   ;2Ah
  144.         DB        09    ;2Bh - Backslash
  145.         DB       0FFh   ;2Ch
  146.         DB       0FFh   ;2Dh
  147.         DB       0FFh   ;2Eh
  148.         DB       0FFh   ;2Fh
  149.         DB       0FFh   ;30h
  150.         DB       0FFh   ;31h
  151.         DB       0FFh   ;32h
  152.         DB        10    ;33h - Comma
  153.         DB        11    ;34h - Period
  154.         DB        12    ;35h - Slash
  155.         DB       0FFh   ;36h
  156.         DB        13    ;37h - Pad-Asterisk
  157.         DB       0FFh   ;38h
  158.         DB       0FFh   ;39h
  159.         DB       0FFh   ;3Ah
  160.         DB       0FFh   ;3Bh
  161.         DB       0FFh   ;3Ch
  162.         DB       0FFh   ;3Dh
  163.         DB       0FFh   ;3Eh
  164.         DB       0FFh   ;3Fh
  165.         DB       0FFh   ;40h
  166.         DB       0FFh   ;41h
  167.         DB       0FFh   ;42h
  168.         DB       0FFh   ;43h
  169.         DB       0FFh   ;44h
  170.         DB       0FFh   ;45h
  171.         DB       0FFh   ;46h
  172.         DB        14    ;47h - Home
  173.         DB        15    ;48h - Up
  174.         DB        16    ;49h - PgUp
  175.         DB        17    ;4Ah - Pad-Minus
  176.         DB        18    ;4Bh - Left
  177.         DB        19    ;4Ch - Pad-5
  178.         DB        20    ;4Dh - Right
  179.         DB        21    ;4Eh - Pad-Plus
  180.         DB        22    ;4Fh - End
  181.         DB        23    ;50h - Down
  182.         DB        24    ;51h - PgDn
  183.         DB        25    ;52h - Insert
  184.         DB        26    ;53h - Del
  185.  
  186. WordTable         LABEL WORD            ;Table of Scan words to return
  187.         ;         Control   Alt
  188.         DW       0FFFFh,    0100h  ;Esc
  189.         DW       0FFFFh,    0E00h  ;Backspace
  190.         DW        9400h,   0A500h  ;Tab
  191.         DW       0FFFFh,    1A00h  ;Left Brack
  192.         DW       0FFFFh,    1B00h  ;Right Brack
  193.         DW       0FFFFh,    1C00h  ;Enter
  194.         DW       0FFFFh,    2700h  ;Semicolon
  195.         DW       0FFFFh,    2800h  ;Quote
  196.         DW       0FFFFh,    2900h  ;Backquote
  197.         DW       0FFFFh,    2B00h  ;Backslash
  198.         DW       0FFFFh,    3300h  ;Comma
  199.         DW       0FFFFh,    3400h  ;Period
  200.         DW       0FFFFh,    3500h  ;Slash
  201.         DW       0FFFFh,    3700h  ;Pad-Asterisk
  202.         DW       0FFFFh,    9700h  ;Home
  203.         DW        8D00h,    9800h  ;Up
  204.         DW       0FFFFh,    9900h  ;PgUp
  205.         DW        8E00h,    4A00h  ;Pad-minus
  206.         DW       0FFFFh,    9B00h  ;Left
  207.         DW        8F00h,    9C00h  ;Pad-5
  208.         DW       0FFFFh,    9D00h  ;Right
  209.         DW        9000h,    4E00h  ;Pad-Plus
  210.         DW       0FFFFh,    9F00h  ;End
  211.         DW        9100h,   0A000h  ;Down
  212.         DW       0FFFFh,   0A100h  ;PgDn
  213.         DW        9200h,   0A200h  ;Insert
  214.         DW        9300h,   0A300h  ;Del
  215.  
  216.         BiosShiftFlags  EQU BYTE PTR 17h  ;Addresses in BIOS data area
  217.         BufferHead      EQU WORD PTR 1Ah
  218.         BufferTail      EQU WORD PTR 1Ch
  219.         BufferStart     EQU WORD PTR 80h
  220.         BufferEnd       EQU WORD PTR 82h
  221.  
  222. NewInt09 PROC FAR
  223.         STI                             ;Interrupts on
  224.         PUSH    AX                      ;Save registers we use
  225.         PUSH    BX
  226.         PUSH    CX
  227.         PUSH    DS
  228.  
  229.         MOV     AX,SEG DATA
  230.         MOV     DS,AX                   ;Point to Turbo data area
  231.         CMP     EnableEnhanced,0        ;Enhanced functions enabled?
  232.         JZ      Int09Orig               ;No, get out
  233.  
  234.         MOV     AX,0040h
  235.         MOV     DS,AX                   ;Point to BIOS data area
  236.  
  237.         MOV     AL,DS:BiosShiftFlags    ;Shift status in AL
  238.         MOV     CL,AL                   ;Save shift state in CL
  239.         TEST    AL,00001100b            ;Either Control or Alt depressed?
  240.         JZ      TestPad5                ;No, check special case of Pad-5
  241.  
  242.         AND     AL,00001100b            ;Just Ctrl-Alt bits
  243.         CMP     AL,00001100b            ;Both Ctrl and Alt depressed?
  244.         JE      Int09Orig               ;Get out in case of Ctrl-Alt-Del
  245.  
  246.         MOV     AL,CL                   ;Restore shift state
  247.         AND     AL,00001111b            ;All shift bits
  248.         CMP     AL,00001010b            ;Just Alt-LeftShift?
  249.         JE      Int09Orig               ;Get out so Alt-Keypad works
  250.  
  251.         IN      AL,60h                  ;Read scan code
  252.         CMP     AL,53h                  ;Is it in range 0..53h?
  253.         JA      Int09Orig               ;If not, pass on to BIOS int 09 handler
  254.  
  255.         MOV     BX,offset IndexTable    ;Point to index table
  256.         XLAT    BYTE PTR CS:[0]         ;Get index
  257.         CMP     AL,0FFh                 ;AL = FFh?
  258.         JNZ     MatchedScan             ;Special case if AL <> FFh
  259.  
  260. Int09Orig:                              ;Let BIOS int 09 handler take care of it
  261.         POP     DS                      ;Restore registers
  262.         POP     CX
  263.         POP     BX
  264.         POP     AX
  265.         JMP     PrevInt09               ;Transfer to previous interrupt 09
  266.  
  267. TestPad5:
  268.         IN      AL,60h                  ;Read scan code
  269.         CMP     AL,4Ch                  ;Pad-5 key?
  270.         JNZ     Int09Orig               ;No, get out
  271.         MOV     AX,4C00h                ;Set up scan code to return
  272.         TEST    CL,00100000b            ;Is NumLock set?
  273.         JZ      NoNumLock               ;No, it's not
  274. NumLockSet:
  275.         TEST    CL,00000011b            ;Is a shift key depressed?
  276.         JNZ     StoreScanWord           ;Yes, we want to store 4C00 in buffer
  277.         JMP SHORT Int09Orig             ;No, let original int 9 do it
  278. NoNumLock:
  279.         TEST    CL,00000011b            ;Is a shift key depressed?
  280.         JZ      StoreScanWord           ;No, store scan word
  281.         JMP SHORT Int09Orig             ;Yes, let original int 9 do it
  282.  
  283. MatchedScan:
  284.         SHL     AX,1                    ;Multiply scan index by 2
  285.         SHL     AX,1                    ;Multiply by 2 again
  286.         MOV     BX,AX                   ;BX = Index * 4
  287.         TEST    CL,00001000b            ;Alt depressed?
  288.         JZ      NoAltKey                ;No, use first column of table
  289.         ADD     BX,2                    ;Yes, use second column of table
  290. NoAltKey:
  291.         MOV     AX,CS:WordTable[BX]     ;Get the scan word
  292.         CMP     AX,0FFFFh               ;Case handled by BIOS?
  293.         JZ      Int09Orig               ;Yes, get out of here
  294.  
  295. StoreScanWord:
  296.         MOV     CX,AX                   ;Save scan word in CX
  297.         IN      AL,61h                  ;Read control port value
  298.         MOV     AH,AL                   ;Save in AH
  299.         OR      AL,80h                  ;Set high bit
  300.         OUT     61h,AL                  ;Reset keyboard
  301.         MOV     AL,AH                   ;Retrieve original value
  302.         OUT     61h,AL                  ;Enable keyboard
  303.         CLI                             ;Stop CPU interrupts
  304.         MOV     AL,20h                  ;End of interrupt
  305.         OUT     20h,AL                  ;To the interrupt controller
  306.  
  307.         MOV     BX,DS:BufferTail        ;Point to end of keyboard buffer
  308.         MOV     AX,BX                   ;Transfer to AX
  309.         ADD     AX,0002                 ;Advance to next position
  310.         CMP     AX,DS:BufferEnd         ;Wrap around if needed
  311.         JNE     CheckFull               ;No need to wrap
  312.         MOV     AX,DS:BufferStart       ;Else to beginning of buffer
  313. CheckFull:
  314.         CMP     AX,DS:BufferHead        ;Bumping in to start?
  315.         JE      NewInt09Done            ;Exit if full
  316.         MOV     [BX],CX                 ;Store keystroke
  317.         MOV     DS:BufferTail,AX        ;Advance tail
  318. NewInt09Done:
  319.         STI                             ;Interrupts on
  320.         POP     DS                      ;Restore registers
  321.         POP     CX
  322.         POP     BX
  323.         POP     AX
  324.         IRET                            ;Return to caller
  325. NewInt09 ENDP
  326.  
  327. ;*********************************************************** NewInt16
  328. ;Handle software keyboard interrupts
  329. NewInt16 PROC FAR
  330.         PUSH    DX                      ;Save registers we use
  331.         PUSH    DS
  332.         PUSHF                           ;Save flags
  333.         STI                             ;Allow interrupts
  334.  
  335.         MOV     DX,SEG DATA
  336.         MOV     DS,DX                   ;Assure DS points to Turbo data
  337.         CMP     EnableEnhanced,0        ;Enhanced functions enabled?
  338.         JZ      Int16Orig               ;No, pass to previous int 16
  339.         CMP     HasEnhancedKbd,0        ;Is enhanced keyboard installed?
  340.         JZ      Int16Orig               ;No, leave call alone
  341.  
  342.         OR      AH,AH                   ;AH=0?
  343.         JNZ     TryAH1                  ;No, try AH=1
  344. AH0:
  345.         OR      AH,10h                  ;Use enhanced BIOS call instead
  346.         CALL    PrevInt16               ;Call previous int 16 (pops flags)
  347.         OR      AH,AH                   ;AH=0?
  348.         JZ      AH0Done                 ;Yes, done
  349.         CMP     AL,0E0h                 ;AL=E0h?
  350.         JNZ     AH0Done                 ;No, leave it alone
  351.         XOR     AL,AL                   ;Clear low byte of scan word
  352. AH0Done:
  353.         POP     DS                      ;Restore registers
  354.         POP     DX
  355.         IRET                            ;Return to caller
  356.  
  357. TryAH1:
  358.         CMP     AH,1                    ;AH=1?
  359.         JNZ     Int16Orig               ;No, let original int 16 do it
  360. AH1:
  361.         OR      AH,10h                  ;Use enhanced BIOS call instead
  362.         CALL    PrevInt16               ;Call previous int 16 (pops flags)
  363.         PUSHF                           ;Save result flags
  364.         JZ      AH1Done                 ;Just return if no key available
  365.         OR      AH,AH                   ;AH=0?
  366.         JZ      AH1Done                 ;Yes, done
  367.         CMP     AL,0E0h                 ;AL=E0h?
  368.         JNZ     AH1Done                 ;Yes, clear it
  369.         XOR     AL,AL                   ;Clear low byte of scan word
  370. AH1Done:
  371.         POPF                            ;Restore result flags
  372.         POP     DS                      ;Restore registers
  373.         POP     DX
  374.         RET     2                       ;Return with flags intact
  375.  
  376. Int16Orig:
  377.         POPF                            ;Restore flags
  378.         POP     DS
  379.         POP     DX
  380.         JMP     PrevInt16               ;Let old int16 handle the rest
  381. NewInt16 ENDP
  382.  
  383. ;*********************************************************** InitVectors
  384. ;Save and setup interrupt vectors
  385. InitVectors PROC NEAR
  386.         MOV     AX,3509h                ;Get current int 9
  387.         INT     21h
  388.         MOV     PrevInt09Ofs,BX         ;Save it in CS-relative variables
  389.         MOV     PrevInt09Seg,ES
  390.         PUSH    DS
  391.         PUSH    CS
  392.         POP     DS
  393.         MOV     DX,offset NewInt09
  394.         MOV     AX,2509h                ;Install new int 9
  395.         INT     21h
  396.         POP     DS
  397.         MOV     AX,3516h                ;Get current int 16
  398.         INT     21h
  399.         MOV     PrevInt16Ofs,BX         ;Save it in CS-relative variables
  400.         MOV     PrevInt16Seg,ES
  401.         PUSH    DS
  402.         PUSH    CS
  403.         POP     DS
  404.         MOV     DX,offset NewInt16
  405.         MOV     AX,2516h                ;Install new int 16
  406.         INT     21h
  407.         POP     DS
  408.         RET
  409. InitVectors ENDP
  410.  
  411. CODE    ENDS
  412.         END
  413.